import pygame
from game_item import *
from game_hud import *
from game_music import *
import random

class Game(object):
    """游戏核心类"""
    def __init__(self):
        #游戏窗口
        self.main_window=pygame.display.set_mode(SCREEN_RECT.size)
        pygame.display.set_caption("飞机大战")

        #游戏状态
        self.is_game_over=False
        self.is_game_pause=False
        #游戏精灵组
        self.all_group=pygame.sprite.Group()#存放所有精灵
        self.enemies_group = pygame.sprite.Group()#敌机精灵
        self.supplies_group = pygame.sprite.Group()#道具精灵
        #游戏精灵
        #创建背景精灵
        self.all_group.add(Background(False),Background(True))
        # 创建游戏控制面板
        self.hud_panel = HUDPanel(self.all_group)
        #创建英雄飞机精灵
        self.hero_sprite=Hero(self.all_group)
        self.hud_panel.show_bomb(self.hero_sprite.bomb_count)

        #初始化敌机
        self.create_enemies()
        #初始化道具
        self.create_supply()


        # 音乐播放器
        self.player=MusicPlayer('game_music.ogg')
        self.player.play_music()


    def reset_game(self):
        """游戏重置数据"""
        self.is_game_over=False
        self.is_game_pause = False
        #重置面板
        self.hud_panel.reset_panel()

        #重置英雄飞机位置
        self.hero_sprite.rect.midbottom=HERO_DEFAULT_MID_BOTTOM

        #销毁所有的敌人飞机
        for enemy in self.enemies_group:
            enemy.kill()
        #销毁所有的子弹
        for bullet in self.hero_sprite.bullets_group:
            bullet.kill()
        #重新重建飞机
        self.create_enemies()


    def start(self):
        """开启游戏主逻辑"""
        #创建时钟
        clock=pygame.time.Clock()
        #动画帧数计数器
        frame_count=0
        while True:
            #判断英雄是否已经死亡
            self.is_game_over=self.hud_panel.lives_count==0
            #处理事件监听
            if self.event_handler():
                #event_handler返回True,则说明发生了退出事件

                #退出游戏之前要保存最好的成绩
                self.hud_panel.save_best_score()
                return
            #根据游戏状态切换界面显示的内容
            if self.is_game_over:
                # print("游戏已经结束，按空格建重新开始...")
                self.hud_panel.panel_pause(True,self.all_group)
            elif self.is_game_pause:
                # print('游戏已经暂停，按空格键继续....')
                self.hud_panel.panel_pause(False,self.all_group)
            else:
                self.hud_panel.panel_resume(self.all_group)

                #处理长按事件
                keys=pygame.key.get_pressed()  #get_pressed()得到一个元组
                move_hor=keys[pygame.K_RIGHT]-keys[pygame.K_LEFT]#水平的移动基数
                move_ver=keys[pygame.K_DOWN] - keys[pygame.K_UP]  #垂直的移动基数

                #检测碰撞
                self.check_collide()

                frame_count=(frame_count+1)% FRAME_INTERVAL
                self.all_group.update(frame_count==0,move_hor,move_ver)
            #绘制内容
            self.all_group.draw(self.main_window)
            #刷新界面
            pygame.display.update()
            #设置刷新率
            clock.tick(60)

    def event_handler(self):
        """获取并处理事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                #退出按钮被点击
                return True
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                #用户按下了键盘上的ESC建
                return True
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                #用户按下了键盘上的空格建
                if self.is_game_over:
                    #游戏已经结束，重置游戏
                    self.reset_game()
                else:
                    #游戏还没结束，切换暂停状态
                    self.is_game_pause=not self.is_game_pause
                    self.player.pause_music(self.is_game_pause)#切换背景音乐状态


            #必须在游戏结束也没暂停才能执行的操作
            if not self.is_game_over and not self.is_game_pause:
                if event.type==pygame.KEYDOWN and event.key == pygame.K_b:

                    #释放一颗炸弹，修改炸弹数量
                    if self.hero_sprite.hp>0 and self.hero_sprite.bomb_count>0:
                        self.player.play_sound('use_bomb.wav')

                    score=self.hero_sprite.blowup(self.enemies_group)
                    self.hud_panel.show_bomb(self.hero_sprite.bomb_count)
                    if self.hud_panel.increase_score(score):
                        self.create_enemies()
                elif event.type == HERO_DEAD_EVENT:
                    #玩家飞机死亡
                    self.hud_panel.lives_count-=1
                    self.hud_panel.show_lives()
                    self.hud_panel.show_bomb(self.hero_sprite.bomb_count)
                elif event.type ==HERO_POWER_OFF_EVENT:
                    #无敌事件结束
                    self.hero_sprite.is_power=False
                    pygame.time.set_timer(HERO_POWER_OFF_EVENT,0)#设置定时器延时为0，可以取消定时器

                elif event.type == HERO_FIRE_EVENT:
                    self.player.play_sound('bullet.wav')
                    #英雄飞机发射子弹定时事件
                    self.hero_sprite.fire(self.all_group)

                elif event.type == THROW_SUPPLY_EVENT:
                    #随机抛物一个道具
                    self.player.play_sound('supply.wav')
                    supply=random.choice(self.supplies_group.sprites())
                    supply.throw_supply()
                elif event.type ==BULLET_ENHANCED_OFF_EVENT:
                    #修改玩家使用双排子弹的时间已经结束，需要恢复为单排子弹
                    self.hero_sprite.bullets_kind=0
                    pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT,0)#取消定时



        return False

    def create_enemies(self):
        """创建敌机"""
        count=len(self.enemies_group.sprites())
        groups=(self.all_group,self.enemies_group)
        #根据不同的关卡创建不同数量的敌机
        if self.hud_panel.level == 1 and count == 0:
            #关卡1
            for i in range(16):
                Enemy(0,3,*groups)
        elif self.hud_panel.level == 2 and count == 16:
            #关卡2
            for enemy in self.enemies_group.sprites():
                enemy.max_speed=5
            for i in range(8):
                Enemy(0,5,*groups)
            for i in range(2):
                Enemy(1,1,*groups)
        elif self.hud_panel.level == 3 and count == 26:
            #关卡3
            for enemy in self.enemies_group.sprites():
                enemy.max_speed=7 if enemy.kind ==0 else 3
            for i in range(8):
                Enemy(0,7,*groups)
            for i in range(2):
                Enemy(1,3,*groups)
            for i in range(2):
                Enemy(2,1,*groups)

    def check_collide(self):
        """检查是否有碰撞"""
        if not self.hero_sprite.is_power:#没有无敌才需要检查碰撞
            collide_enemies=pygame.sprite.spritecollide(self.hero_sprite,
                                                    self.enemies_group,
                                                    False,pygame.sprite.collide_mask)
            collide_enemies=list(filter(lambda x:x.hp>0,collide_enemies))
            #撞毁玩家飞机
            if collide_enemies:
                self.player.play_sound(self.hero_sprite.wav_name)
                self.hero_sprite.hp=0
            #撞毁敌人飞机
            for enemy in collide_enemies:
                enemy.hp = 0

            #子弹和敌机的碰撞分析
            hit_enemies=pygame.sprite.groupcollide(self.enemies_group,self.hero_sprite.bullets_group,
                                       False,False,pygame.sprite.collide_mask)
            for enemy in hit_enemies:

                #已经被摧毁的飞机不需要再处理
                if enemy.hp<=0:
                    continue
                for bullet in hit_enemies[enemy]:
                       bullet.kill()    #销毁子弹
                       enemy.hp -= bullet.damage  #修改敌机生命值

                       if enemy.hp>0:
                            continue         #如果敌机没有被摧毁，则继续遍历下一颗子弹

                        #当前这一颗已经把敌机摧毁
                       if self.hud_panel.increase_score(enemy.value):
                           self.player.play_sound('upgrade.wav')
                           self.create_enemies()
                       #这个飞机已经被摧毁，不需要再遍历下一颗子弹
                       self.player.play_sound(enemy.wav_name)

                       break
        #检查英雄飞机和道具的碰撞
        supplies=pygame.sprite.spritecollide(self.hero_sprite,self.supplies_group,
                                    False,pygame.sprite.collide_mask)
        if supplies:
            supply=supplies[0]
            self.player.play_sound(supply.wav_name) #根据道具类型播放捡道具的音效

            #根据道具类型产生不同的行为
            if supply.kind ==0:
                self.hero_sprite.bomb_count+=1
                self.hud_panel.show_bomb(self.hero_sprite.bomb_count)

            else:
                self.hero_sprite.bullets_kind=1 #修改英雄子弹为双排
                pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT,20000)#20秒之后重新变为单排子弹

            #移动道具到屏幕之下
            supply.rect.y=SCREEN_RECT.h

    def create_supply(self):
        """初始化两个道具，
        并开启投放道具的定时器
        """
        Supply(0,self.all_group,self.supplies_group)
        Supply(1,self.all_group,self.supplies_group)
        pygame.time.set_timer(THROW_SUPPLY_EVENT,30000)








if __name__ == '__main__':
    #初始化游戏
    pygame.init()
    #开始游戏
    Game().start()
    #释放游戏资源
    pygame.quit()